home *** CD-ROM | disk | FTP | other *** search
/ Hackers Handbook - Millenium Edition / Hackers Handbook.iso / library / hack99 / Sniffer_construction.txt < prev    next >
Encoding:
Text File  |  1999-04-11  |  20.1 KB  |  492 lines

  1.                            Basic Packet-Sniffer Construction
  2.                       from the Ground Up
  3.  
  4.                                        Part 1
  5.                                          by
  6.  
  7.                                      Chad Renfro
  8.                  raw_sock@hotmail.com
  9.  
  10.  
  11.    Packet sniffers are applications used by network administrators to monitor and
  12. validate network traffic. Sniffers are programs used to read packets that travel across 
  13. the network at various levels of the OSI layer. And like most security tools sniffers too
  14. can be used for both good and destructive purposes. On the light-side of network
  15. administration sniffers help quickly track down problems such as bottlenecks and
  16. misplaced filters. However on the dark-side sniffers can be used to reap tremendous
  17. amounts of havoc by gathering legitimate user names and passwords so that other
  18. machines can be quickly compromised. Hopefully this paper will be used to help
  19. administrators gain control of their networks by being able to analyze network traffic 
  20. not only by using preconstructed  sniffers but by being able to create their own. This
  21. paper will look at the packet sniffer from the bottem up, looking in depth at the sniffer
  22. core and then gradualy adding functionality to the application. The example included
  23. here will help illustrate some rather cumbersome issues when dealing with network
  24. programing. In no way will this single paper teach a person to write a complete sniffing
  25. application like tcpdump or sniffit. It will however teach some very fundamental issues
  26. that are inherent to all packet sniffers. Like how the packets are accessed on the network
  27. and how to work with the packets at different layers.
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36. The most basic sniffer...
  37.  
  38. Sniffer #1.
  39.  
  40.    This sniffer will illustrate the use of the  SOCK_RAW device and show how to gather
  41. packets from the network and print out some simple header  information to std_out.
  42. Although the basic premise is that packet sniffers operate  in a promiscuous mode which
  43. listens to all packets weather or not the packet is destined  for the machines mac address,
  44. this example will collect packets in a non-promiscuous mode . This will let usconcentrate
  45. on the SOCK_RAW device for the first example. To operate this same  code  in a
  46. promiscous mode  the network card may be put in a promiscous mode manually. To do
  47. this type this in after the log in :
  48.  
  49.    > su -
  50.    Password : ********
  51.    # ifconfig eth0 promisc
  52.  
  53.    This will now set the network interface eth0 in promiscous mode. 
  54.  
  55.  
  56. /************************simple_Tcp_sniff.c********************/
  57.  
  58. 1.    #include <stdio.h>
  59. 2.    #include <sys/socket.h>
  60. 3.    #include <netinet/in.h>
  61. 4.    #include <arpa/inet.h>
  62.  
  63. 5.    #include "headers.h"
  64.  
  65. 6.    int main()
  66. 7.    {
  67. 8.        int sock, bytes_recieved, fromlen;
  68. 9.        char buffer[65535];
  69. 10.        struct sockaddr_in from;
  70. 11.        struct ip  *ip;
  71. 12.        struct tcp *tcp;
  72. 13.
  73.  
  74. 14.        sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
  75.  
  76. 15.    while(1)
  77. 16.     {
  78. 17.        fromlen = sizeof from;
  79. 18.        bytes_recieved = recvfrom(sock, buffer, sizeof buffer, 0,
  80.                                              (struct sockaddr *)&from, &fromlen);
  81. 19.        printf("\nBytes received ::: %5d\n",bytes_recieved);
  82. 20.        printf("Source address ::: %s\n",inet_ntoa(from.sin_addr));
  83. 21.        ip = (struct ip *)buffer;
  84. 22.        printf("IP header length ::: %d\n",ip->ip_length);
  85. 23.        printf("Protocol ::: %d\n",ip->ip_protocol);
  86. 24.        tcp = (struct tcp *)(buffer + (4*ip->ip_length));
  87. 25.        printf("Source port ::: %d\n",ntohs(tcp->tcp_source_port);
  88. 26.        printf("Dest port  ::: %d\n",ntohs(tcp->tcp_dest_port));
  89.  
  90. 27.             }
  91. 28. }
  92. /***********************EOF**********************************/
  93.  
  94. What this means :
  95.  
  96. Line 1-4 :
  97.    These are the header files required to use some needed c functions we will use later
  98.  
  99.     <stdio.h>      =     functions like printf and std_out
  100.     <sys/socket.h> =     this will give access to the SOCK_RAW and the 
  101.                          IPPROTO_TCP defines     
  102.     <netinet/in.h> =     structs like the sockaddr_in 
  103.     <arpa/inet.h>  =     lets us use the functions to do network to host byte 
  104.                          order conversions
  105. line 5 :
  106.    This is the header file headers.h that is also included with this program to give standard
  107.    structures to access the ip and tcp fields. The structures identify each field in the ip and
  108.    tcp header for instance :
  109.  
  110.     struct ip {
  111.            unsigned int        ip_length:4;         /* length of ip-header in 32-bit
  112.                                                            words*/
  113.             unsigned int        ip_version:4;        /* set to "4", for Ipv4 */
  114.            unsigned char       ip_tos;              /* type of service*/
  115.            unsigned short      ip_total_length;     /* Total length of ip datagram in
  116.                                                            bytes */
  117.            unsigned short      ip_id;               /*identification field*/
  118.            unsigned short      ip_flags;
  119.            unsigned char       ip_ttl;              /*time-to-live, sets upper limit
  120.                                                           for max number of routers to 
  121.                                                           go through before the packet is
  122.                                                           discarded*/
  123.  
  124.            unsigned char       ip_protocol;         /*identifies the correct transport
  125.                                               protocol */
  126.            unsigned short      ip_cksum;            /*calculated for the ip header ONLY*/
  127.                unsigned int        ip_source;           /*source ip */
  128.                unsigned int        ip_dest;             /*dest ip*/
  129.     };
  130.  
  131.  
  132.  
  133.     struct tcp {
  134.                  unsigned short     tcp_source_port; /*tcp source port*/
  135.              unsigned short     tcp_dest_port;   /*tcp dest port*/
  136.              unsigned int       tcp_seqno;       /*tcp sequence number,
  137.                                                        identifies the byte in the 
  138.                                                        stream of data*/
  139.              unsigned int       tcp_ackno;       /*contains the next seq num that
  140.                                                        the sender expects to recieve*/
  141.              unsigned int       tcp_res1:4,      /*little-endian*/
  142.                                     tcp_hlen:4,      /*length of tcp header in 32-bit
  143.                                                        words*/ 
  144.                                 tcp_fin:1,       /*Finish flag "fin"*/
  145.                                     tcp_syn:1,       /*Synchronize sequence
  146.                                                        numbers to start a connection
  147.                             tcp_rst:1,       /*Reset flag */
  148.                                     tcp_psh:1,       /*Push, sends data to the
  149.                                                        application*/
  150.                                     tcp_ack:1,       /*acknowledge*/
  151.                                     tcp_urg:1,       /*urgent pointer*/
  152.                                     tcp_res2:2;
  153.                  unsigned short     tcp_winsize;     /*maxinum number of bytes able
  154.                                                to recieve*/
  155.              unsigned short     tcp_cksum;       /*checksum to cover the tcp
  156.                                                        header and data portion of the
  157.                                                        packet*/
  158.  
  159.              unsigned short     tcp_urgent;     /*vaild only if the urgent flag is
  160.                                           set, used to transmit
  161.                                                       emergency data */
  162.     };
  163.  
  164.  
  165. line 8-13 :
  166.    This is the variable declaration section
  167.       
  168.     integers :
  169.          sock                 = socket file descriptor 
  170.          bytes_recieved       = bytes read from the open socket "sock" 
  171.          fromlen              = the size of the from structure char :
  172.              buffer               = where the ip packet that is read off the 
  173.                             wire will be held buffer will hold a datagram 
  174.                             of 65535 bytes which is the maximum length 
  175.                             of an ip datagram.
  176.  
  177.        Struct sockaddr_in :
  178.  
  179.        struct sockaddr_in {
  180.         short int          sin_family;  /* Address family   */
  181.         unsigned short int sin_port;    /* Port number      */
  182.         struct in_addr     sin_addr;    /* Internet address */
  183.         unsigned char      sin_zero[8]; /* Same size as struct sockaddr */
  184.         };
  185.  
  186.       Before we go any further two topics should be covered,byte-ordering and sockaddr
  187.    structures.  Byte-ordering,is the way that the operating system stores bytes in memory.
  188.    There are two ways that this is done first with the low-order byte at the starting address
  189.    this is known as "little-endian" or host-byte order. Next bytes can be stored with the
  190.    high order byte at the starting address, this is called "big-endian" or network byte order.
  191.    The Internet protocol uses >>>>>> network byte order.
  192.     
  193.        This is important because if you are working on an intel based linux box you will be
  194.    programming on a little-endian machine and to send data via ip you must convert the
  195.    bytes to network-byte order. For examle lets say we are going to store a 2-byte number
  196.    in memory say the value is (in hex) 0x0203
  197.  
  198.  
  199.    First this is how the value is stored on a big-endian machine:
  200.  
  201.                     ___________
  202.                    | 02  | 03  |
  203.                    |_____|_____| 
  204.         address:    0       1
  205.  
  206.  
  207.    And here is the same value on a little-endian machine:
  208.  
  209.                    ___________
  210.                   |03   | 02  |
  211.                   |_____|_____|
  212.        address:    1       0
  213.  
  214.  
  215.  
  216.    The same value is being represented in both examples it is just how we order the bytes
  217.    that changes.
  218.  
  219.    The next topic that you must understand is the sockaddr vs. the sockaddr_in structures.
  220.    The struct sockaddr is used to hold information about the socket such as the family type
  221.    and other address information it looks like :
  222.  
  223.     struct sockaddr {
  224.               unsigned short sa_family;         /*address family*/ 
  225.                   char           sa_data[14];       /*address data*/
  226.     };
  227.      
  228.     
  229.       The first element in the structure "sa_family" will be used to reference what the family
  230.    type is for the socket, in our sniffer it will be AF_INET. Next the "sa_data" element
  231.    holds the destination port and address for the socket. To make it easier to deal with the
  232.    sockaddr struct the use of the sockaddr_in structure is commonly used. Sockaddr_in 
  233.    makes it easier to reference all of the elements that are contained by sockaddr.
  234.  
  235.  
  236.    Sockaddr_in looks like:
  237.  
  238.  
  239.  
  240.    struct sockaddr_in {
  241.              short int          sin_family;    /* Address family               */
  242.              unsigned short int sin_port;      /* Port number                  */
  243.              struct in_addr     sin_addr;      /* Internet address             */
  244.              unsigned char      sin_zero[8];   /* Same size as struct sockaddr */
  245.    };
  246.  
  247.  
  248.  
  249.  
  250.  
  251.  
  252.  
  253.       We will use this struct and declare a variable "from" which will give us the information
  254.    on the packet that we will collect from the raw socket. For instance the var
  255.    "from.sin_addr" will give access to the packets source address (in 
  256.    network byte order). The thing to mention here is that all items in the sockaddr_in
  257.    structure must be in network-byte order. When we receive the data in the sockaddr_in
  258.    struct we must then convert it back to Host-byte order. To do this we can use some
  259.    predefined functions to convert back and forth between  host and network byteorder.
  260.  
  261.    Here are the functions we will use:
  262.  
  263.     ntohs       : this function converts  network byte order to host byte order
  264.                       for a 16-bit short
  265.  
  266.     ntohl       : same as above but for a 32-bit long
  267.  
  268.     inet_ntoa   : this function converts a 32-bit network binary value to a
  269.                       dotted decimal ip address
  270.  
  271.     inet_aton   : converts a character string  address to the 32-bit network
  272.                       binary value
  273.  
  274.     inet_addr   : takes a char string dotted decimal addr and returns a 32-bit
  275.                       network binary value
  276.  
  277.    To further illustrate ,say I want to know the port number that this packet originated from:
  278.  
  279.     int packet_port; packet_port    =ntohs(from.sin_port);
  280.                                  ^^^^^    
  281.  
  282.    If I want the source IP address of the packet we will use a special function to get it to the
  283.    123.123.123.123 format:
  284.  
  285.     char *ip_addr; ip_addr    =inet_ntoa(from.sin_addr)
  286.                          ^^^^^^^^^
  287.  
  288. line 11-12:
  289.  
  290.    struct ip *ip :
  291.    struct tcp *tcp :
  292.     
  293.       This is a structure that we defined in our header file "headers.h". This structure is
  294.    declared so that we can access individual fields of the ip/tcp header. The structure is like
  295.    a transparent slide with predefined fields drawn on it. When a packet is taken off 
  296.    the wire it is a stream of bits, to make sense of it the "transparency" (or cast) is laid on
  297.    top of or over the bits so the individual fields can be referenced.
  298.  
  299. Line 14 :
  300.  
  301.    sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
  302.  
  303.    This is the most important line in the entire program. Socket() takes three arguments in
  304.    this form:
  305.  
  306.     sockfd = socket(int family, int type, int protocol);
  307.  
  308.  
  309.  
  310.     
  311.     The first argument is the family. This could be either AF_UNIX which is used so a process
  312.    can communicate with another process on the same host or AF_INET which is used for
  313.    internet communication between remote hosts. In this case it will be  AF_INET . Next  
  314.    is the type, the type is usually between 1 of 4 choices (there are others that we will not
  315.    discuss here) the main four are :
  316.  
  317.    1.    SOCK_DRAM      : used for udp datagrams
  318.    2.    SOCK_STREAM    : used for tcp packets
  319.    3.    SOCK_RAW       : used to bypass the transport layer
  320.                      and directly access the IP layer
  321.  
  322.    4.    SOCK_PACKET    : this is linux specific, it is similuar to
  323.                          SOCK_RAW except it accesses the DATA LINK Layer
  324.  
  325.       For our needs we will use the SOCK_RAW type. You must have root acces to open a
  326.     raw socket. The last parameter  is the protocol,the protocol value specifies what type of
  327.     traffic the socket should receive , for normal sockets this value is usally set to "0"
  328.     because the socket can figure out if for instance the "type" of SOCK_DGRAM is
  329.     specified then the protocol should be UDP.In our case we just want to look at tcp 
  330.     traffic so we will specify IPPROTO_TCP.
  331.  
  332.     
  333. line 15 :
  334.    while (1)
  335.  
  336.   The while (1) puts the program into an infinite loop this is necessary so that after the
  337.  first packet is processed we will loop around and grab the next. 
  338.  
  339.  
  340. Line 18:
  341.    bytes_recieved = recvfrom(sock, buffer, sizeof buffer, 0, (struct sockaddr *)&from, &fromlen);
  342.     
  343.    Now here is where we are actually reading data from the open socket "sock".The from
  344.    struct is also filled in but notice that we are casting "from" from a "sockaddr_in" struct
  345.    to a "sockaddr" struct. We do this because the recvfrom() requires a sockaddr type but
  346.    to access the separate fields we will continue to use the sockaddr_in structure. The 
  347.    length of the "from" struct must also be present and passed by address. The recvfrom()
  348.    call will return the number of bytes on success and a -1 on error and fill the global var
  349.    errno.
  350.  
  351.    This is what we call "blocking-I/O" the recvfrom() will wait here forever until a
  352.    datagram on the open socket is ready to be processed. This is opposed to 
  353.    Non-blocking I/O which is like running a process in the background and move on to
  354.    other tasks.
  355.  
  356.  
  357. Line 20:
  358.    printf("Source address ::: %s\n",inet_ntoa(from.sin_addr));
  359.  
  360.    This printf uses the special function inet_ntoa() to take the value of "from.sin_addr"
  361.    which is stored in Network-byte order and outputs a value in a readable ip form such
  362.    as 192.168.1.XXX.
  363.  
  364. Line 21:
  365.    ip = (struct ip *)buffer;
  366.  
  367.    This is where we will overlay a predefined structure that will help us to individually
  368.    identify the fields in the packet that we pick up from the open socket.
  369.  
  370.  
  371. Line 22:
  372.    printf("IP header length ::: %d\n",ip->ip_length);
  373.  
  374.    The thing to notice on this line is the "ip->ip_length" this will access a pointer in
  375.    memory to the ip header length the important thing to remember is that the length 
  376.    will be represented in 4-byte words this will be more important later when trying to
  377.    access items past the ip header such as the tcp header or the data portion of the packet.
  378.  
  379.  
  380.  
  381. Line 23:
  382.    printf("Protocol ::: %d\n",ip->ip_protocol);
  383.     
  384.    This gives access to the type of protocol such as 6 for tcp or 17 for udp.
  385.  
  386. Line 24:
  387.    tcp = (struct tcp *)(buffer + (4*ip->ip_length));
  388.  
  389.        Remember earlier it was mentioned that the ip header length is stored in 4 byte words,
  390.    this is where that bit of information becomes important. Here we are trying to get access
  391.    to the tcp header fields, to do this we must overlay a structure that has the fields
  392.    predefined just as we did with ip. There is one key difference here the ip header fields
  393.    were easy to access due to the fact that the beginning of the buffer was also the beginning
  394.    of the ip header as so :
  395.  
  396.     
  397.     |----------------- buffer ----------------|
  398.      _________________________________________
  399.     | ip header          |                    |
  400.            |____________________|____________________|
  401.                              ^
  402.                              *ip
  403.                              ^
  404.                              *buffer
  405.  
  406.       So to get access to the ip header we just set a pointer casted as an ip structure to the
  407.    beginning of the buffer like "ip = (struct ip *)buffer;". To get access to the tcp header 
  408.    is a little more difficult due to the fact that we must set a pointer and cast it as a tcp
  409.    structure at the beginning of the tcp header which follows the ip header in the buffer 
  410.    as so :
  411.  
  412.     
  413.      |----------------- buffer ---------------|
  414.           ________________________________________
  415.          | ip header | tcp header |               |
  416.          |___________|____________|_______________|
  417.                      ^
  418.                      *tcp
  419.                         
  420. This is why we use 4*ip->ip_length to find the start of the tcp header.
  421.  
  422. Line 25-26:
  423.     printf("Source port ::: %d\n",ntohs(tcp->tcp_source_port);
  424.     printf("Dest port  ::: %d\n",ntohs(tcp->tcp_dest_port));
  425.  
  426.    We can now access the source and dest ports which are located in the tcp header via 
  427.    the structure as defined above.
  428.  
  429.  
  430.  
  431.  
  432.      This will conclude  our  first very simple tcp sniffer. This was a very basic application
  433.    that should help define how  to access packets passing on the network and how  to use
  434.    sockets to access the packets. Hopefully this will be the first of many papers to come,
  435.    which each proceeding paper we will add a new or more complex feature to the sniffer. I
  436.    should also mention that there a number of great resources on the net that should aid you
  437.    in further research in this area :
  438.  
  439.     1. Beej's Guide to Network Programming
  440.          This is an awesome paper that really helps 
  441.          clear up any misconceptions about network programming.
  442.                 [http://www.ecst.csuchico.edu/~beej/guide/net]
  443.  
  444.         2. TCP/IP Illustrated Vol 1,2,3
  445.            W.Richard Stevens
  446.  
  447. To use the above program, cut out the above code and strip off all 
  448. of the line numbers. Save the edited file as sniff.c. Next cut 
  449. out the header file headers.h (below) and save it to a file headers.h
  450. in the same directory. Now just compile: gcc -o sniff sniff.c
  451. You should now have the executable "sniff", to run it type
  452. #./sniff
  453.  
  454. /*************************headers.h**************************/
  455. /*structure of an ip header             */
  456. struct ip {
  457.     unsigned int        ip_length:4;    /*little-endian*/
  458.     unsigned int        ip_version:4;
  459.     unsigned char       ip_tos;
  460.     unsigned short      ip_total_length;
  461.     unsigned short      ip_id;
  462.     unsigned short      ip_flags;
  463.     unsigned char       ip_ttl;
  464.     unsigned char       ip_protocol;
  465.     unsigned short      ip_cksum;
  466.     unsigned int        ip_source;
  467.     unsigned int        ip_dest;
  468. };
  469.  
  470. /* Structure of a TCP header */
  471. struct tcp {
  472.     unsigned short      tcp_source_port;
  473.     unsigned short      tcp_dest_port;
  474.     unsigned int        tcp_seqno;
  475.     unsigned int        tcp_ackno;
  476.     unsigned int        tcp_res1:4,     /*little-endian*/
  477.     tcp_hlen:4,
  478.     tcp_fin:1,
  479.      tcp_syn:1,
  480.     tcp_rst:1,
  481.     tcp_psh:1,
  482.     tcp_ack:1,
  483.     tcp_urg:1,
  484.     tcp_res2:2;
  485.     unsigned short      tcp_winsize;
  486.     unsigned short      tcp_cksum;
  487.     unsigned short      tcp_urgent;
  488. };
  489. /*********************EOF***********************************/
  490.  
  491.  
  492.